﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Configuration;
using ThousandFunClient.model;
using ThousandFunClient.Util;
using System.Collections;
using System.IO.Ports;
using System.Timers;
using log4net;
using System.Globalization;
using System.Threading;
using System.Media;
using System.Runtime.InteropServices;

namespace ThousandFunClient
{
    public partial class Fm_ThounsandFunMain : Form
    {
        public Fm_ThounsandFunMain()
        {
            InitializeComponent();
            try
            {
                ConfigUtil.initConfig();
                lbl_warn.Text = "";
                lbl_error.Text = "";
   
                Constants.syslogger.Info("System Start");

                sp_Torque = new SerialPort();
                PortUtil.SetPortByConfig(sp_Torque, TFConfig.GetInstance().PortConfigA);
                PortUtil.OpenCOM(sp_Torque);
                sp_Torque.DataReceived += sp_Torque_DataReceived;

                nowBatchData.AngleValue = "0.0";
                nowBatchData.TorqueValue = "0.0";
                nowBatchData.CycleNum = 0;
                tf_process();
            }
            catch (Exception exc)
            {
                Constants.syslogger.Error("initError:", exc);
                lbl_error.Text = "PortA端口打开错误";
            }

            if (TFConfig.GetInstance().PortConfigB.BcouldUsed)
            {
                try
                {
                    sp_Send = new SerialPort();
                    PortUtil.SetPortByConfig(sp_Send, TFConfig.GetInstance().PortConfigB);
                    PortUtil.OpenCOM(sp_Send);
                }
                catch (Exception exb)
                {
                    Constants.syslogger.Error("portBError:", exb);
                    TFConfig.GetInstance().PortConfigB.BcouldUsed = false;
                    lbl_error.Text = "PortB端口打开错误";
                }
            }

            if (TFConfig.GetInstance().PortConfigC.BcouldUsed)
            {
                try
                {
                    sp_PortC = new SerialPort();
                    PortUtil.SetPortByConfig(sp_PortC, TFConfig.GetInstance().PortConfigC);
                    PortUtil.OpenCOM(sp_PortC);
                }
                catch (Exception exb)
                {
                    Constants.syslogger.Error("portCError:", exb);
                    TFConfig.GetInstance().PortConfigC.BcouldUsed = false;
                    lbl_error.Text = "PortC端口打开错误";
                }
            }
            
        }


        private void btn_error_Click(object sender, EventArgs e)
        {
            fm_about.Show(); 
        }

        private void Fm_ThounsandFunMain_Load(object sender, EventArgs e)
        {

        }

        private void btn_start_Click(object sender, EventArgs e)
        {
            statusChange(false,true);         
        }

        private void statusChange(bool forceFlag,bool runStatus)
        {
            try
            {
                if (!forceFlag)
                {
                    runStatus = !timer_Torque.Enabled;
                }

                if (runStatus)
                {
                    timer_Torque.Enabled = true;
                    timer_PortC.Enabled = true;
                    btn_start.Text = "停止"; 
                }
                else
                {
                    timer_Torque.Enabled = false;
                    timer_PortC.Enabled = false;
                    btn_start.Text = "启动";
                }
            }
            catch (Exception exb)
            {
                Constants.syslogger.Error("portAError:", exb);

                lbl_error.Text = "停止端口错误";
            }

        }


        public void tf_process() 
        {
            timer_Torque = new System.Timers.Timer();
            timer_Torque.Interval = Int32.Parse(TFConfig.GetInstance().TorqueConfig.Interval);
            timer_Torque.Elapsed += new ElapsedEventHandler(timer_TorqueEvent);
            timer_Torque.Enabled = true;

            timer_PortC = new System.Timers.Timer();
            timer_PortC.Interval = Int32.Parse(System.Configuration.ConfigurationSettings.AppSettings["PortCInterval"]);
            timer_PortC.Elapsed += new ElapsedEventHandler(timer_PortCEvent);
            timer_PortC.Enabled = true;
        }

        private void batchCMDrun(bool timerEvent)
        {

            if (timerEvent)
            {
                if (DataUtil.isBatchDataOK(nowBatchData))
                {
                    preBatchDataSuccess = (BatchData)nowBatchData.Clone();
                    
                    nowCount = 0;
                    tempbuf = null;
                    Invoke(new MethodInvoker(delegate { lbl_warn.Text = ""; }));
                    nowBatchData = new BatchData();
                }
                else
                {
                    Invoke(new MethodInvoker(delegate { txt_torque.Text = ""; }));
                    Invoke(new MethodInvoker(delegate { txt_angle.Text = ""; }));
                    Invoke(new MethodInvoker(delegate { txt_programNo.Text = ""; }));
                    Invoke(new MethodInvoker(delegate { txt_programStep.Text = ""; }));
                    Invoke(new MethodInvoker(delegate { lbl_warn.Text = "通讯错误"; }));
                    nowCount = 0;
                    tempbuf = null;
                    nowBatchData = new BatchData();
                }
            }

            if (nowCount >= TFConfig.GetInstance().HtRunning.Count)
            {
                nowCount = 0;
                return;
            }

            if (!nowRunning.Equals(""))
            {
                //出错处理

            }

            String temp = (String)TFConfig.GetInstance().HtRunning[nowCount];
            string sendcmd = "";
            if (temp.Equals(Constants.Cycle))
            {
                sendcmd = TFConfig.GetInstance().CycleNumberConfig.SendCMD;
            }
            else if (temp.Equals(Constants.Torque))
            {
                sendcmd = TFConfig.GetInstance().TorqueConfig.SendCMD;
            }
            else if (temp.Equals(Constants.Angle))
            {
                sendcmd = TFConfig.GetInstance().AngleConfig.SendCMD;
            }
            else if (temp.Equals(Constants.ProgramNo))
            {
                sendcmd = Constants.ProgramNoCMD;
            }
            else if (temp.Equals(Constants.ProgramStep))
            {
                sendcmd = Constants.ProgramStepCMD;
            }
            else if (temp.Equals(Constants.PMStatus))
            {
                sendcmd = Constants.PMStatusCMD;
            }

            byte[] bs = DataUtil.convertSendDataBytes(sendcmd);
            sp_Torque.Write(bs, 0, bs.Length);

            Constants.syslogger.Debug("Send:");
            Constants.syslogger.Debug(bs);
            nowRunning = temp;
            Constants.loggersp.Error(nowRunning + "Send:" + sendcmd);

        }

        private void timer_TorqueEvent(object source, ElapsedEventArgs e)
        {
            batchCMDrun(true);

        }



        public string genSendPortcCMD()
        {
            string sendPortcCMD = "";

            string gg = DataUtil.inttohex(int.Parse(System.Configuration.ConfigurationSettings.AppSettings["PortCSendProgramNo"]));
            byte[] g = System.Text.Encoding.ASCII.GetBytes(gg);
            sendPortcCMD = "02 " + g[0];
            byte[] c = System.Text.Encoding.ASCII.GetBytes("$");

            sendPortcCMD = sendPortcCMD + " 36 36 36 36 36 03";
            
            return sendPortcCMD;
        }

        private void timer_PortCEvent(object source, ElapsedEventArgs e)
        {

            if (TFConfig.GetInstance().PortConfigC.BcouldUsed)
            {
                byte[] bs = DataUtil.convertPortCSendDataBytes(this.genSendPortcCMD());
                sp_PortC.Write(bs, 0, bs.Length);
                Constants.syslogger.Debug("SendPortC:");
                Constants.syslogger.Debug(bs);
            }

        }

        private void sp_Torque_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                int int_Len = sp_Torque.BytesToRead;

                byte[] buf = new byte[int_Len];

                sp_Torque.Read(buf, 0, int_Len);

                Constants.syslogger.Debug("receive:");
                Constants.syslogger.Debug(buf);

                if (DataUtil.verifyData(buf)) 
                {
                    processDatarec(buf);
                    tempbuf = null;
                }
                else
                {
                    byte[] tempbufcom = DataUtil.byteAdd(tempbuf, buf);
                    tempbuf = tempbufcom;
                    if (DataUtil.verifyData(tempbuf))
                    {
                        processDatarec(tempbuf);
                        tempbuf = null;
                    }
                }

                
            }
            catch (Exception exc)
            {
                Constants.syslogger.Error("datarec:", exc);
            }
            
        }

        private void processDatarec(byte[] buf)
        {

            TFModel tfmodel = DataUtil.parseReceiveint(buf);
            if (nowRunning.Equals(Constants.Cycle))
            {
                int cc = int.Parse(tfmodel.Answerdata, NumberStyles.HexNumber);
                nowBatchData.CycleNum = cc;

                if (nowBatchData.CycleNum != nowNoAlertCyclenum)
                {
                    nowNoAlertCyclenum = 999999;
                }

            }
            else if (nowRunning.Equals(Constants.Torque))
            {
                Int64 cc = Int64.Parse(tfmodel.Answerdata, NumberStyles.HexNumber);
                double dTorque = Double.Parse(cc.ToString()) / 65535;
                nowBatchData.TorqueValue = DataUtil.formatDisStr(dTorque);
                Invoke(new MethodInvoker(delegate { txt_torque.Text = nowBatchData.TorqueValue; }));
            }
            else if (nowRunning.Equals(Constants.Angle))
            {
                Int64 cc = Int64.Parse(tfmodel.Answerdata, NumberStyles.HexNumber);
                double dAngle = Double.Parse(cc.ToString()) / 65535;
                nowBatchData.AngleValue = DataUtil.formatDisStr(dAngle);

                Invoke(new MethodInvoker(delegate { txt_angle.Text = nowBatchData.AngleValue; }));

            }
            else if (nowRunning.Equals(Constants.ProgramNo))
            {
                Int64 cc = Int64.Parse(tfmodel.Answerdata, NumberStyles.HexNumber);
                
                nowBatchData.ProgramNoValue = cc.ToString();

                if (nowBatchData.ProgramNoValue != System.Configuration.ConfigurationSettings.AppSettings["PortCSendProgramNo"])
                {
                    Invoke(new MethodInvoker(delegate { lbl_warn.Text = "程序选择器中设置的程序号与实际运行程序号不符，请检查程序选择器连线是否松开，软件中Port C的端口号、波特率设置是否正确，或更换程序程序选择器后重新测试。如仍无效，请与上海动纳动力科技有限公司相关技术工程师联系。"; }));
                }
                Invoke(new MethodInvoker(delegate { txt_programNo.Text = nowBatchData.ProgramNoValue; }));
            }
            else if (nowRunning.Equals(Constants.ProgramStep))
            {
                Int64 cc = Int64.Parse(tfmodel.Answerdata, NumberStyles.HexNumber);
                cc = cc + 1;
                nowBatchData.ProgramStepValue = cc.ToString();
                Invoke(new MethodInvoker(delegate { txt_programStep.Text = nowBatchData.ProgramStepValue; }));
            }
            else if (nowRunning.Equals(Constants.PMStatus))
            {
                Int64 cc = Int64.Parse(tfmodel.Answerdata, NumberStyles.HexNumber);
                nowBatchData.PMStatusValue = cc.ToString();
                if (nowBatchData.PMStatusValue.Equals("0"))
                {
                    Invoke(new MethodInvoker(delegate
                    {
                        txt_torque.BackColor = Color.Green;
                        txt_angle.BackColor = Color.Green; 
                    
                    }));

                }
                else
                {
                    //循环号为0的时候不报警也不显示红色
                    if (!nowBatchData.ProgramNoValue.Trim().Equals("0"))
                    {
                        Invoke(new MethodInvoker(delegate
                        {
                            if (nowBatchData.CycleNum == nowNoAlertCyclenum)
                            {
                                Constants.syslogger.Error("StopAlert:" + nowBatchData.CycleNum.ToString());
                            }
                            else
                            {
                                System.Media.SoundPlayer sp = new SoundPlayer();
                                sp.SoundLocation = @"alert.wav";
                                sp.Play();
                            }
                            txt_torque.BackColor = Color.Red;
                            txt_angle.BackColor = Color.Red;

                        }));
                    }
                }

                if (DataUtil.isBatchDataEnd(nowBatchData))
                {
                    try
                    {
                        //判断记录log并且发送PortB
                        //循环号为0的时候不存储
                        if (!nowBatchData.ProgramNoValue.Trim().Equals("0"))
                        {
                            if (nowBatchData.CycleNum != preBatchDataSuccess.CycleNum || nowBatchData.ProgramNoValue != preBatchDataSuccess.ProgramNoValue)
                            {
                                Constants.loggerfinal.Error(nowBatchData.toCSVStr());
                                if (TFConfig.GetInstance().PortConfigB.BcouldUsed)
                                {
                                    DataUtil.sendDatePortB(nowBatchData, sp_Send);
                                    Constants.loggerSend.Error("log:" + nowBatchData.toSendStr());
                                }
                            }
                        }

                    }
                    catch (Exception exc)
                    {
                        Constants.syslogger.Error("PortSend:", exc);
                    }
                }
            }


            Constants.loggersp.Error(nowRunning + "Reply:" + tfmodel.ToLogString());

            nowCount = nowCount + 1;
            batchCMDrun(false);
        }


        void CrossThreadCall_Local(string reply)
        {
            txt_torque.Text = reply;
        }


        public delegate void void_d(string reply);

        public void openPorts()
        {
            PortUtil.OpenCOM(sp_Torque);
            if (TFConfig.GetInstance().PortConfigB.BcouldUsed)
            {
                PortUtil.OpenCOM(sp_Send);
            }
            if (TFConfig.GetInstance().PortConfigC.BcouldUsed)
            {
                PortUtil.OpenCOM(sp_PortC);
            }
        }

        public void shutdownport()
        {
            PortUtil.CloseCom(sp_Torque);
            if (TFConfig.GetInstance().PortConfigB.BcouldUsed)
            {
                PortUtil.CloseCom(sp_Send);
            }
            if (TFConfig.GetInstance().PortConfigC.BcouldUsed)
            {
                PortUtil.CloseCom(sp_PortC);
            }
            
        }
       

        private int nowCount = 0;
        private string nowRunning = "";
        private int nowNoAlertCyclenum = 999999;
        private System.Timers.Timer timer_Angle;

        private System.Timers.Timer timer_Torque;
        private System.Timers.Timer timer_PortC;
        public SerialPort sp_Torque;
        public SerialPort sp_Send;
        public SerialPort sp_PortC;

        private BatchData preBatchDataSuccess = new BatchData();

        private BatchData nowBatchData = new BatchData();

        private byte[] tempbuf;
        

        private void timer_Main_Tick(object sender, EventArgs e)
        {
  
            lbl_date.Text = DateUtil.GetInstance().CurrentTime.ToString("d");
            lbl_time.Text = DateUtil.GetInstance().CurrentTime.ToString("T");

        }

        private Fm_ErrorDis fm_ErrorDis = new Fm_ErrorDis();

        private void button1_Click_1(object sender, EventArgs e)
        {
            Boolean runStatus = new Boolean();
            MessageBox.Show(runStatus.ToString());
            BatchData ccfcg = new BatchData();
            MessageBox.Show(ccfcg.CycleNum.ToString());
            MessageBox.Show(ccfcg.AngleSend);
            nowBatchData.CycleNum = 123;

            nowBatchData.AngleValue = "123asdf";

            preBatchDataSuccess = (BatchData)nowBatchData.Clone();

            nowBatchData.CycleNum = 1235;

            nowBatchData.AngleValue = "12353asdf";
            MessageBox.Show(preBatchDataSuccess.CycleNum.ToString());

            MessageBox.Show(preBatchDataSuccess.AngleValue);

        }

        private void btn_config_Click(object sender, EventArgs e)
        {
            statusChange(true, false);
            shutdownport();

            DialogResult dr = fm_TF_Config.ShowDialog();
            if (dr == DialogResult.Cancel)
            {
                openPorts();

            }
            
        }


        private Fm_TF_Config fm_TF_Config = new Fm_TF_Config();
        private Fm_About fm_about = new Fm_About();
        private Fm_Exit fm_exit = new Fm_Exit();
        private Fm_ProNo_config fm_ProNo_config = new Fm_ProNo_config();

        private void button4_Click(object sender, EventArgs e)
        {
            fm_ProNo_config.ShowDialog();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            nowNoAlertCyclenum = nowBatchData.CycleNum;

        }

        private void button5_Click(object sender, EventArgs e)
        {
            fm_exit.Owner   =   this;    
            fm_exit.ShowDialog();
 
        }

        private void button3_Click(object sender, EventArgs e)
        {
            label1.Text = "S|" +  System.DateTime.Now.ToString() + "|E";
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }
    
    }
}
